package com.wormhole.wormholemanagement.service.impl;

import com.wormhole.wormholemanagement.controller.response.PersonPositionResponse;
import com.wormhole.wormholemanagement.dto.PersonPositionDTO;
import com.wormhole.wormholemanagement.dto.PersonPositionResponseDTO;
import com.wormhole.wormholemanagement.entity.Person;
import com.wormhole.wormholemanagement.entity.PersonPosition;
import com.wormhole.wormholemanagement.entity.PersonPositionId;
import com.wormhole.wormholemanagement.entity.Position;
import com.wormhole.wormholemanagement.exception.WormException;
import com.wormhole.wormholemanagement.repository.PersonPositionRepository;
import com.wormhole.wormholemanagement.repository.PersonRepository;
import com.wormhole.wormholemanagement.repository.PositionRepository;
import com.wormhole.wormholemanagement.service.PersonPositionService;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
@RequiredArgsConstructor
public class PersonPositionServiceImpl implements PersonPositionService {
    private final PersonRepository personRepository;
    private final PositionRepository positionRepository;
    private final PersonPositionRepository personPositionRepository;

    @Override
    public List<PersonPositionResponseDTO> searchPersonPositions(String name, String title) {
        List<PersonPosition> personPositions = personPositionRepository.search(name, title);
        return mapToResponseDTOs(personPositions);
    }

    @Override
    public PersonPositionResponseDTO addPersonPosition(PersonPositionDTO dto) {
        // 查找或创建人员
        Person person = personRepository.findByName(dto.getPersonName())
                .orElseGet(() -> {
                    Person newPerson = new Person();
                    newPerson.setName(dto.getPersonName());
                    return personRepository.save(newPerson);
                });

        // 处理职位
        List<Position> positions = processPositions(dto.getPositionTitles());

        // 保存关联关系
        positions.forEach(position -> {
            PersonPositionId id = new PersonPositionId(person.getPersonId(), position.getPositionId());
            if (!personPositionRepository.existsById(id)) {
                PersonPosition personPosition = new PersonPosition();
                personPosition.setId(id);
                personPosition.setPerson(person);
                personPosition.setPosition(position);
                personPosition.setIsCurrent(true);
                personPositionRepository.save(personPosition);
            }
        });

        return getPersonPositionResponseDTO(person.getPersonId());
    }

    @Override
    public PersonPositionResponseDTO updatePersonPosition(Long personId, PersonPositionDTO dto) {
        // 查找人员
        Person person = personRepository.findById(personId)
                .orElseThrow(() -> new WormException("Person not found with id: " + personId));

        // 更新人员姓名（如果需要）
        if (!person.getName().equals(dto.getPersonName())) {
            person.setName(dto.getPersonName());
            personRepository.save(person);
        }

        // 处理职位
        List<Position> newPositions = processPositions(dto.getPositionTitles());
        Set<Long> newPositionIds = newPositions.stream().map(Position::getPositionId).collect(Collectors.toSet());

        // 获取现有关联
        List<PersonPosition> existingPersonPositions = personPositionRepository.findByPersonId(personId);
        Set<Long> existingPositionIds = existingPersonPositions.stream()
                .map(pp -> pp.getPosition().getPositionId())
                .collect(Collectors.toSet());

        // 删除不再需要的关联
        existingPersonPositions.forEach(pp -> {
            if (!newPositionIds.contains(pp.getPosition().getPositionId())) {
                personPositionRepository.delete(pp);
            }
        });

        // 添加新的关联
        newPositions.forEach(position -> {
            if (!existingPositionIds.contains(position.getPositionId())) {
                PersonPosition personPosition = new PersonPosition();
                personPosition.setId(new PersonPositionId(personId, position.getPositionId()));
                personPosition.setPerson(person);
                personPosition.setPosition(position);
                personPosition.setIsCurrent(true);
                personPositionRepository.save(personPosition);
            }
        });

        return getPersonPositionResponseDTO(personId);
    }

    @Override
    public void deletePersonPosition(Long personId) {
        // 删除关联关系
        personPositionRepository.deleteByPersonId(personId);
        // 删除人员
        personRepository.deleteById(personId);
    }

    @Override
    public List<PersonPositionResponseDTO> getAllPersonPositions() {
        List<PersonPosition> personPositions = personPositionRepository.findAll();
        return mapToResponseDTOs(personPositions);
    }

    private List<Position> processPositions(List<String> positionTitles) {
        if (positionTitles == null || positionTitles.isEmpty()) {
            return Collections.emptyList();
        }

        // 查找已存在的职位
        List<Position> existingPositions = positionRepository.findByTitleIn(positionTitles);
        Set<String> existingTitles = existingPositions.stream()
                .map(Position::getTitle)
                .collect(Collectors.toSet());

        // 创建不存在的职位
        List<Position> newPositions = positionTitles.stream()
                .filter(title -> !existingTitles.contains(title))
                .map(title -> {
                    Position position = new Position();
                    position.setTitle(title);
                    return positionRepository.save(position);
                })
                .collect(Collectors.toList());

        // 合并所有职位
        List<Position> allPositions = new ArrayList<>(existingPositions);
        allPositions.addAll(newPositions);

        return allPositions;
    }

    private PersonPositionResponseDTO getPersonPositionResponseDTO(Long personId) {
        Person person = personRepository.findById(personId)
                .orElseThrow(() -> new WormException("Person not found with id: " + personId));

        List<PersonPosition> personPositions = personPositionRepository.findByPersonId(personId);
        List<String> positionTitles = personPositions.stream()
                .map(pp -> pp.getPosition().getTitle())
                .collect(Collectors.toList());

        return new PersonPositionResponseDTO(
                person.getPersonId(),
                person.getName(),
                positionTitles,
                person.getCreatedAt(),
                person.getUpdatedAt()
        );
    }

    private List<PersonPositionResponseDTO> mapToResponseDTOs(List<PersonPosition> personPositions) {
        Map<Person, List<String>> personToTitlesMap = personPositions.stream()
                .collect(Collectors.groupingBy(
                        PersonPosition::getPerson,
                        Collectors.mapping(pp -> pp.getPosition().getTitle(), Collectors.toList())
                ));

        return personToTitlesMap.entrySet().stream()
                .map(entry -> new PersonPositionResponseDTO(
                        entry.getKey().getPersonId(),
                        entry.getKey().getName(),
                        entry.getValue(),
                        entry.getKey().getCreatedAt(),
                        entry.getKey().getUpdatedAt()
                ))
                .collect(Collectors.toList());
    }
}